var CONFIG = require('../../../../common/config');
var Alipay = require('alipay-node-sdk');
var path = require('path');
var request = require('request');
var xml2js = require('xml2js');
var async = require('async');
var crypto = require('crypto');

var ItbAddressModel = require('../../../../common/mysql/mapping/ItbAddressModel');
var ItbTradeOrderModel = require('../../../../common/mysql/mapping/ItbTradeOrderModel');
var ItbCartModel = require('../../../../common/mysql/mapping/ItbCartModel');
var CommonUtil = require('../../../../common/util/CommonUtil');
var ItbTradeOrderDetailModel = require('../../../../common/mysql/mapping/ItbTradeOrderDetailModel');
var ItbCouponModel = require('../../../../common/mysql/mapping/ItbCouponModel');
var ItbInvoiceModel = require('../../../../common/mysql/mapping/ItbInvoiceModel');
var ItbPaymentHisModel = require('../../../../common/mysql/mapping/ItbPaymentHisModel');
var ItbTradeStateHisModel = require('../../../../common/mysql/mapping/ItbTradeStateHisModel');
var ItbBuyTmplModel = require('../../../../common/mysql/mapping/ItbBuyTmplModel');
var ItbQtyPriceModel = require('../../../../common/mysql/mapping/ItbQtyPriceModel');
var WeChatPay = require('./WeChatPay');
// 注意: 老一键生成支付工具类, 订单后续发货流程较多, 暂时引用, 尽量不使用该工具类
var oldYjscPayUtil = require('../../../routes/util/payUtil');

var optionsForAliPay = {
    appId: '2018041602565700',
    rsaPrivate: path.resolve(__dirname, '../../ext/alipay_yjsc_private_key.pem'),
    rsaPublic: path.resolve(__dirname, '../../ext/alipay_yjsc_ali_public_key.pem'),
    sandbox: false,
    signType: 'RSA2',
    notifyUrl: 'https://paycb.itbour.com:818/payment/chkAlipayNotify'   // 正式支付回调
};
var optionsForAppWeChatPay = {
    appId: 'wxb6504bf6ff28cb10',                // APP的APPID(微信开放平台审核通过的应用APPID)
    mchId: '1419473302',                        // 商户ID
    key: 'Wefub8730xfyFekodbfgoFQmmnOwEREp',    // ［key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置］
    notifyUrl : 'https://paycb.itbour.com:818/payment/chkWxPayNotify'   // 正式回调地址
};
// 测试环境更改回调地址
if(CONFIG.DEBUG) {
    // 测试环境 支付回调
    optionsForAliPay.notifyUrl = 'http://test.itbour.com:3006/payment/chkAlipayNotify';
    optionsForAppWeChatPay.notifyUrl = 'http://test.itbour.com:3006/payment/chkWxPayNotify';
}
/*
* IAP 商品表, 价格为 key, 单位: 分, 商品标识为 value
* */
var YJSC_IAP_ITEMS_MAP = {
    '29800' : '0000000001',     // 会员原价
    '19800' : '0000000002',     // 会员优惠100
    '9800' : '0000000003',      // 季度会员
    '4500' : '0000000004',       // 月度会员,
    '7800' : 'yjsc_season_minus_20', // 新版季度会员
    '3000' : 'yjsc_month_minus_15',  // 新版月度会员
};

/*
* 切记:
* 1. 官方未提供 nodejs sdk, 此处使用 alipay-node-sdk 是自行签名操作, 使用签名时一定使用第二种生成方式, 官方提供工具有问题
* 2. 阿里公钥是 txt 形式, 转 pem 格式, 添加 begin 头 end 尾, 每64字符换行,
* */
var yjscAlipayClient = new Alipay(optionsForAliPay);
var yjscAppWeChatPay = new WeChatPay(optionsForAppWeChatPay);

var orderUtil = (function () {

    function orderUtil() {

    }

    // 测试订单验证
    orderUtil.verAliPayParams = function (options, callback) {
        var response = {"gmt_create":"2018-04-17 17:39:49","charset":"utf-8","seller_email":"2113934743@qq.com","subject":"一键生成测试订单","sign":"MdDRbUUnQCARzmwZtvDbT/fnbLkWHhPWV3QGCKuwG6YmaEHgZvL0YeeN2/7ytW5h0KVwSGcClYlUq1A0rQLCyqKqwi6ShxwvyLU/XIuDRxN30VPhBb74AuvGViW+JSarOHE9aaNrSuTzR4VSth5ieuYuW8g1BcS/HTbaL5xflfG5AN4FgNXyFYda63c72F35Aa0AylyfjBQQhSsqagVyZ1S66DDX/BYXAiW4tdGEOBR6ALF6UnmL7nrly6QtjEvfC6pr1cath44t3/GJc4Jw2eL6Z3C4cBPFZo1sRBBJr1ij845feBNUQ5KwYOs9vTCAXXQ3+gqJqB4y7QvRO+fDUQ==","body":"交易描述","buyer_id":"2088802690032804","invoice_amount":"0.01","notify_id":"b7c313f414440940d2a1aeaa404bcefm6d","fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"0.01","app_id":"2018041602565700","buyer_pay_amount":"0.01","sign_type":"RSA2","seller_id":"2088521383898083","gmt_payment":"2018-04-17 17:39:50","notify_time":"2018-04-17 17:43:03","version":"1.0","out_trade_no":"1523957923783","total_amount":"0.01","trade_no":"2018041721001004800545923891","auth_app_id":"2018041602565700","buyer_logon_id":"182****6313","point_amount":"0.00"};
        var valid = yjscAlipayClient.signVerify(response);
        console.log("signVerify: " + valid);
        return callback(null, valid);
    };

    /**
     * 免费订单处理(零元)
     *
     * @author 王俊
     * @date 2018-04-19
     *
     * @param {Object} options
     * @param {Number} options.orderId  订单唯一标识
     * @param {Number} options.orderNo  订单号
     * @param {Number} options.orderType  订单类型
     * @param {Number} options.userId   用户唯一标识
     * @param {Function} callback 回调
     *                      err: 处理失败
     */
    orderUtil.processFreeOrder_v6_4 = function (options, callback) {
        var totalTasks = [];
        // 1. 插入支付成功记录
        totalTasks.push(function (callback) {
            // 添加支付历史纪录
            var insEnt = new ItbPaymentHisModel({
                type:  options.orderType ||0,
                trade_obj_id: options.orderId ||0,
                trade_obj_no: options.orderNo ||0,
                state: 11,
                pay_platform: 0,// 无
                desc: 'SUCCESS',
                update_by: options.userId||0
            });
            insEnt.saveToDB(function(insErr, newHisId) {
                if(insErr) {
                    console.log("payUtil.js [getUnifiedOrder] Ins PayHis Err: " + insErr);
                }
                return callback(null, {});
            });
        });
        // 2. 处理支付成功后续处理
        totalTasks.push(function (data, callback) {
            var param = {
                userId : options.userId,
                tradeType : options.orderType,
                tradeObjId : options.orderId,
                tradeState : 11,
                totalFee : 0
            };
            oldYjscPayUtil.payNotifyProcCore(param, function (error) {
                return callback(error, data);
            });
        });
        async.waterfall(totalTasks, function (error, data) {
            return callback(error, data);
        });
    };

    /**
     * 获取订单的支付参数
     *
     * @author 王俊
     * @date 2018-04-18
     *
     * @param {Object} options 请求参数
     * @param {Number} options.userId 用户标识
     * @param {Number} options.orderId 订单标识
     * @param {Number} options.orderType 订单类型 商品订单: 10   发票订单: 20
     * @param {Number} options.device 设备标识
     * @param {Function} callback 回调函数
     *                      err: 获取出错
     *                      data: {
     *                          "orderId" : 3546,
                                "orderNo" : "QWERTYUIO",
                                "orderFee" : 989000,        // 订单支付金额, 单位: 分
                                "paymentPlatform" : 10,     // 支付平台, 10微信, 20支付宝
                                "wechat" : {               // 微信支付相关参数如下
                                    // 网页支付存在
                                    "codeUrl" : "weixin://xxx.jpg",
                                    // APP 支付存在
                                    "prepayId": "1101000000140415649af9fc314aa427",
                                    "nonceStr": "a462b76e7436e98e0ed6e13c64b4fd1c",
                                    "timeStamp": "1397527777",
                                    "sign": "582282D72DD2B03AD892830965F428CB16E7A256",
                                },
                                "alipay" : {
                                    "orderStr": "app_id=2018022402264996&biz_content=%7B%22body%22%3A%22%E4%BA%A4%E6%98%93%E6%8F%8F%E8%BF%B0%22%2C%22subject%22%3A%22%E4%B8%80%E9%94%AE%E7%A7%80%E6%B5%8B%E8%AF%95%E8%AE%A2%E5%8D%95%22%2C%22out_trade_no%22%3A%221523931796606%22%2C%22timeout_express%22%3A%221h%22%2C%22total_amount%22%3A%220.01%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22goods_type%22%3A%220%22%7D&charset=utf-8&format=JSON&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fwww.yijianxiu.com%2F&sign_type=RSA2&timestamp=2018-04-17%2010%3A23%3A16&version=1.0&sign=YIl3tXVYNDgx052%2FKnKGRchx5X14Mj%2B6hMRUXAuHs1msG%2Bu16HLeVErEj3cZ0HB%2FLitfV6S4lZi9IZ%2F63Q8edrxlRtzXelUnWD53rGbMBMrUcjsgQ05dHHojXCRs5QDjvxxIbafD%2FbFo802n%2FhU1jsMbHF6N%2FYqy%2FRQ4gIyDWJJFxPYPKBDw%2BICQwyJbqz1V2Gkn1OzqwbSYsOswUcZIIpTlGEgjiO5jH8QYzsJSLx4Gb5SVVdzzsdkGbq25c%2Bs2albKWH4qHLy6jjPY%2BCAulKR%2BxKHH7Beg%2B0XJfR1ozGN%2BIKEfMp4T8IZ5GzdDAcnyft%2Bz%2BsS4Y6pYlgI7iqjhCA%3D%3D"
                                },
                                "IAP" : {
                                    "productIdentifier" : "00000001"
                                }
     *                      }
     */
    orderUtil.getOderPaymentParams = function (options, callback) {
        var totalTasks = [];
        // 1. 查询订单信息
        totalTasks.push(function (callback) {
            var  entity = null;
            if(options.orderType === 20) {
                entity = new ItbInvoiceModel({
                    inv_id : options.orderId,
                    del_flg : 0
                });
            } else {
                entity = new ItbTradeOrderModel({
                    order_id : options.orderId,
                    del_flg : 0
                });
            }
            entity.findFromDB(function (error, orders) {
                if(error || !orders || orders.length <=0) {
                    return callback(error || '该订单不存在', null);
                }
                var order = orders[0];
                // 订单状态:10待支付、11已支付、12支付失败、20制作中、30配送中、40完成、50取消
                if([11,20,30,40,50].indexOf(order.state) >=0) {
                    return callback('订单已支付或取消, 无需重复支付', null);
                }
                if(order.user_id !== options.userId) {
                    return callback('不能支付非本账户订单', null);
                }
                var data = {};
                data.isInvoiceOrder = options.orderType === 20;
                data.isInvoiceOrder ? data.invoiceEntity = order : data.orderEntity = order;
                return callback(error, data);
            });
        });
        // 2. 获取订单信息, 订单类型, 是否为实物等
        totalTasks.push(function (data, callback) {
            if(data.isInvoiceOrder) {
                data.orderType = 20;    // 发票订单
                return callback(null, data);
            }
            var entity = new ItbTradeOrderDetailModel();
            entity.checkTradeOrderTypeInfo(options.orderId, function (error, typeInfo) {
                if(error || !typeInfo) {
                    return callback('查询订单类型失败', null);
                }
                data.orderType = typeInfo.orderType;
                return callback(error, data);
            });
        });

        // 3. 获取订单金额订单号等, 创建支付订单
        totalTasks.push(function (data, callback) {
            if (data.isInvoiceOrder) {
                data.orderId = data.invoiceEntity.inv_id;
                data.orderNo = data.invoiceEntity.inv_no;
                data.orderFee = data.invoiceEntity.mail_fee;
                data.payPlatform = data.invoiceEntity.pay_platform;
            } else {
                data.orderId = data.orderEntity.order_id;
                data.orderNo = data.orderEntity.order_no;
                data.orderFee = data.orderEntity.total_fee;
                data.payPlatform = data.orderEntity.pay_platform
            }
            if(data.orderFee === 0) {
                // 订单金额等于零处理
                var opt = {
                    orderId : data.orderId,
                    orderNo : data.orderNo,
                    orderType : data.orderType,
                    userId : options.userId
                };
                orderUtil.processFreeOrder_v6_4(opt, function (error, result) {
                    return callback(error, data);
                });
                return;
            }
            // 10微信, 20支付宝 30 IAP
            if (data.payPlatform === 10) {
                var opt = {
                    userId : options.userId,
                    orderType : data.orderType,
                    orderId : data.orderId,
                    orderNo : data.orderNo,
                    amount : data.orderFee
                };
                // 测试环境价格固定
                if(CONFIG.DEBUG) {
                    opt.amount = 1; // 本地测试环境, orderFee 固定为1
                }
                orderUtil.getWeChatPaymentParams(opt, function (error, payParams) {
                    data.wechatPayParams = payParams;
                    return callback(error, data);
                })
            } else if(data.payPlatform === 20) {
                var goodsType = data.orderType === 40 ? 0 : 1;
                var opt = {
                    userId : options.userId,
                    orderType : data.orderType,
                    orderId : data.orderId,
                    orderNo : data.orderNo,
                    amount : data.orderFee,
                    goodsType : goodsType
                };
                // 测试环境价格固定
                if(CONFIG.DEBUG) {
                    opt.amount = 1; // 本地测试环境, orderFee 固定为1
                }
                orderUtil.getAlipayPaymentParams(opt, function (error, payParams) {
                    data.alipayPayParams = payParams;
                    return callback(error, data);
                })
            } else if(data.payPlatform === 30) {
                var opt = {
                    amount : data.orderFee
                };
                orderUtil.getIAPPaymentParams(opt, function (error, payParams) {
                    data.IAPPayParams = payParams;
                    return callback(error, data);
                })

            } else {
                return callback('暂不支持的支付方式', data);
            }
        });
        async.waterfall(totalTasks, function (error, data) {
            if(error) return callback(error, null);
            var ret = {
                orderId : data.orderId,
                orderNo : data.orderNo,
                orderFee: data.orderFee,
                paymentPlatform : data.payPlatform,
                wechat : data.wechatPayParams,
                alipay : data.alipayPayParams,
                IAP : data.IAPPayParams
            };
            return callback(error, ret);
        })
    };
    /**
     * 获取微信支付参数
     *
     * @author 王俊
     * @date 2018-04-18
     *
     * @param {Object} options 请求参数
     * @param {Object} options.userId 用户唯一标识
     * @param {Object} options.orderType 订单类型, 10 标记商品订单, 20 标记发票订单, 40 标记虚拟商品顶大
     * @param {Object} options.orderId 订单唯一标识
     * @param {Object} options.orderNo 商户订单号
     * @param {Object} [options.body] 订单内容
     * @param {Object} options.amount 订单金额, 单位: 分
     * @param {Object} [options.isH5] 是否为h5订单, 默认不是
     *
     * @param {Function} callback 回调函数
     *                      err: 请求失败
     *                      data: {
     *                          codeUrl : 二维码链接, web 用
     *                          prepayId: 预支付 id
     *                          nonceStr: 随机字符串
     *                          timeStamp: 时间戳
     *                          sign: 签名
     *                      }
     */
    orderUtil.getWeChatPaymentParams = function (options, callback) {
        if(options.isH5) return callback('暂不支持h5支付', null);
        // 给支付回调携带参数
        var param = {uid: options.userId ||0, id: options.orderId||0, type: options.orderType||0};
        yjscAppWeChatPay.appPay({
            body : options.body || '示界港微信支付订单',
            outTradeNo : options.orderNo,
            totalFee : options.amount,
            attach : JSON.stringify(param)
        }, function (error, data) {
            return callback(error, data);
        });
    };

    /**
     * 获取支付宝支付参数
     *
     * @author 王俊
     * @date 2018-04-18
     *
     * @param {Object} options 请求参数
     * @param {Object} options.userId 用户唯一标识
     * @param {Object} options.orderType 订单类型, 10 标记商品订单, 20 标记发票订单, 40 标记虚拟商品顶大
     * @param {Object} options.orderId 订单唯一标识
     * @param {Object} options.orderNo 商户订单号
     * @param {Object} [options.subject] 订单标题
     * @param {Object} [options.body] 订单内容
     * @param {Object} [options.timeout] 过期时间
     * @param {Object} options.amount 订单金额, 单位: 分
     * @param {Object} options.goodsType 0—虚拟类商品，1—实物类商品 注：虚拟类商品不支持使用花呗渠道
     *
     * @param {Function} callback 回调函数
     *                      err: 请求失败
     *                      data: {
     *                          orderStr : ""   // 支付宝支付参数
     *                      }
     */
    orderUtil.getAlipayPaymentParams = function (options, callback) {
        // 给支付回调携带参数
        var param = {uid: options.userId ||0, id: options.orderId||0, type: options.orderType||0};
        var str = yjscAlipayClient.appPay({
            subject : options.subject || "示界港支付宝支付订单",
            body : options.body || "示界港支付宝支付订单",
            outTradeId : options.orderNo,
            timeout : options.timeout || "2h",
            amount : (options.amount / 100).toFixed(2),
            goodsType : options.goodsType,
            passbackParams : JSON.stringify(param)
        });
        var data = {
            orderStr : str
        };
        return callback(null, data);
    };

    /**
     * 获取苹果支付参数
     *
     * @author 王俊
     * @date 2018-04-18
     *
     * @param {Object} options 请求参数
     * @param {Number} options.amount 支付金额, 单位: 分
     * @param {Function} callback 回调
     *                      err: 错误
     *                      data: {
     *                          productIdentifier : "0000001"
     *                      }
     */
    orderUtil.getIAPPaymentParams = function (options, callback) {
        var data = {};
        data.productIdentifier = YJSC_IAP_ITEMS_MAP[options.amount];
        if(CONFIG.DEBUG && !data.productIdentifier) {
            data.productIdentifier = YJSC_IAP_ITEMS_MAP['4500'];
        }
        if(!data.productIdentifier) {
            return callback('暂不支持应用内购买', null);
        }
        return callback(null, data);
    };

    //-------------------------------------------------------------------
    /**
     * 获取用户结算时使用的地址 id
     *
     * @param userId 用户唯一标识
     * @param addressId 初始地址 id, 若此 id 有效, 则此函数立即回调, 并传递该地址 id
     * @param callback 回调
     *              error 若获取失败, 此为错误原因
     *              addressId 查询到最合适的地址 id, 若用户当前不存在地址, 返回 0
     *
     * 拷贝于 /routes/util/userUtil.js
     * */
    orderUtil.getUserAddressIdForSettlement_v5_7 = function (userId, addressId, callback) {

        if(addressId && addressId >0) {
            return callback(null, addressId);
        }

        addressId = 0;
        // 1. 获取用户默认地址
        var address = new ItbAddressModel({
            user_id : userId,
            type : 1,
            default : 1,
            del_flg : 0
        });
        address.findFromDB(function(defErr, result){
            if(defErr) {
                return callback(defErr, addressId);
            }

            // 找到默认地址, 则返回默认地址 id
            if(result && result.length > 0) {
                return callback(null, result[0].addr_id);
            }

            // 没有默认地址, 获取最新地址
            orderUtil.getUserAddressList_v5_7(userId, 0, 1, 0,function(lastErr, result1){

                if(lastErr) {
                    return callback(lastErr, 0);
                }
                if(result1 && result1.length >0) {
                    return callback(null, result1[0].addr_id);
                }
                // 最新地址也没有
                return callback(null, addressId);
            });

        }, 0, 1);
    };

    /**
     * 获取用户地址列表
     *
     * 拷贝于 /routes/util/userUtil.js
     *
     * @param userId    用户唯一标识
     * @param pageNum   页码
     * @param pageSize  页容量
     * @param withTotalPage  是否获取总页数
     * @param callback  回调函数
     *             err:  查询失败
     *             result: {
     *                  list:   地址列表
     *                  pageNum: 当前页码
     *                  totalPage:
     *             }
     */
    orderUtil.getUserAddressList_v5_7=function(userId, pageNum, pageSize, withTotalPage,callback) {
        var ent = new ItbAddressModel;
        // 取type＝1的数据
        ent.getAddrListByUserId(userId, pageNum, pageSize, function(err, results){
            if(err) {
                return callback(err, null);
            }
            var retData = {list:[], pageNum:pageNum};
            if(!results || results.length <=0) {
                return callback(null, retData);
            }

            for(var i=0; i<results.length; i++) {
                retData.list.push({
                    id: results[i].addr_id,
                    mobile: results[i].mobile,
                    name: results[i].name,
                    prov: {
                        id: results[i].prov,
                        text: results[i].prov_name
                    },
                    city: {
                        id: results[i].city,
                        text: results[i].city_name
                    },
                    dist: {
                        id: results[i].dist,
                        text: results[i].dist_name
                    },
                    detail: results[i].detail,
                    default: results[i].default
                });
            }
            if(!withTotalPage) {
                return callback(null, retData);
            }
            // 取count
            ent.getAddrListByUserIdCnt(userId, function(err2, cnt) {
                if (err2) {
                    return callback(err2, null);
                }
                retData.totalPage = Math.ceil(cnt/pageSize);
                return callback(null, retData);
            });
        });
    };

    /**
     * 根据单个商品信息创建商品子订单数组
     *
     * 注意: 此方法仅供 /yjsc/v2/util/orderUtil.js orderUtil.createOrderFromCart_v6_4 调用
     *
     * @author 王俊
     * @date 2018-04-19
     *
     * @param {Object} options 请求参数
     * @param {Array} options.goodsInfo 商品数组
     * @param {Number} options.orderId 主订单 id
     * @param {Number} options.userId 主订单 id
     * @param {Number} options.mailType 邮费类型
     * @param {Number} options.index 商品编号
     * @param {Function} callback
     *                      err: 创建失败
     *                      data: {
     *                          newOrderDetailId: 商品子订单 id
     *                          assyDetailIds: 商品配件子订单列表
     *                      }
     */
    orderUtil.createGoodsDetailOrder_v6_4 = function (options, callback) {

        var totalTasks = [];
        // 1. 插入商品子订单
        var goodsInfo = options.goodsInfo;
        totalTasks.push(function (callback) {
            // 子订单(主商品)
            var newSubEntity = new ItbTradeOrderDetailModel({
                detail_no: options.index+'_0',
                order_id: options.orderId,
                partner_id: goodsInfo.platform_id||0,// 合作方
                item_id: goodsInfo.item_id,
                pp_id: goodsInfo.pp_id,
                unit: goodsInfo.unit,
                qty: goodsInfo.qty,
                user_doc_id: goodsInfo.user_doc_id,
                fee: Number(goodsInfo.item_fee||'0'),
                product_fee: Number(goodsInfo.item_product_fee||'0'),
                design_fee: Number(goodsInfo.item_design_fee||'0'),
                mail_fee: Number(goodsInfo.item_mail_fee||'0'),
                update_by: options.userId
            });
            // 到付邮费
            if(options.mailType === 20) {
                newSubEntity.fee = newSubEntity.fee - newSubEntity.mail_fee;
                newSubEntity.mail_fee = 0;
            }
            // 创建子订单
            newSubEntity.saveToDB(function(err, newOrderDetailId){
                if(err || !newOrderDetailId) {
                    return callback(err || '创建子订单失败', null);
                }
                var data = {};
                data.newOrderDetailId = newOrderDetailId;
                return callback(null, data);
            });
        });
        // 按需处理配件
        totalTasks.push(function (data, callback) {
            if(!goodsInfo.assyList || goodsInfo.assyList.length<=0) {
                return callback(null, data);
            }
            // 循环处理配件
            var tasks = [];
            for(var j=0; j<goodsInfo.assyList.length; j++){
                tasks.push((function (index2, assyInfo) {
                    return function (asyncCallback2) {
                        // 子订单(配件)
                        var newAssyEntity = new ItbTradeOrderDetailModel({
                            base_detail_id: data.newOrderDetailId,
                            detail_no: j+'_'+Number(index2+1),
                            order_id: options.orderId,
                            partner_id: assyInfo.platform_id||0,// 合作方
                            item_id: assyInfo.item_id,
                            pp_id: assyInfo.pp_id,
                            unit: assyInfo.unit,
                            qty: assyInfo.qty,
                            fee: Number(assyInfo.item_fee||'0'),
                            product_fee: Number(assyInfo.item_product_fee||'0'),
                            design_fee: Number(assyInfo.item_design_fee||'0'),
                            mail_fee: Number(assyInfo.item_mail_fee||'0'),
                            update_by: options.userId
                        });
                        // 到付邮费
                        if(options.mailType === 20) {
                            newAssyEntity.fee = newAssyEntity.fee - newAssyEntity.mail_fee;
                            newAssyEntity.mail_fee = 0;
                        }
                        // 创建子订单
                        newAssyEntity.saveToDB(function(err2, newOrderDetailId2){
                            return asyncCallback2(err2, newOrderDetailId2);
                        });
                    }
                })(j, goodsInfo.assyList[j]));
            }
            async.series(tasks, function (error, results) {
                data.assyDetailIds = results;
                return callback(error, results);
            });
        });
        async.waterfall(totalTasks, function (err, data) {
            return callback(err, data);
        });
    };

    /**
     *  根据购物车信息创建订单
     *
     *  @author 王俊
     *  @date 2018-04-19
     *
     *  @param {Object} options
     *  @param {Number} options.device      设备标识, 见接口定义
     *  @param {Number} options.userId      用户唯一标识
     *  @param {Number} options.couponId    优惠券标识
     *  @param {Number} options.mailType    邮费支付方式
     *  @param {Number} options.addrId      地址标识
     *  @param {Number} options.payPlatform 支付方式 10 微信, 20 支付宝, 30 苹果内购
     *  @param {Function} callback          创建回调
     *                      err:            创建失败
     *                      data: {
     *                          orderId
     *                          orderNo
     *                          totalFee
     *                      }
     * */
    orderUtil.createOrderFromCart_v6_4 = function(options,callback) {

        var totalTasks = [];
        // 1. 获取选中商品信息
        totalTasks.push(function (callback) {
            // 获取选中商品信息
            (new ItbCartModel).procGetPrepayOrderInfo3(options.userId, options.couponId, options.addrId, function(getErr, retGoods){
                if(getErr || !retGoods || retGoods.length <=0) {
                    return callback(getErr || '暂无选中商品', null);
                }
                var retFeeInfo = retGoods[0];
                if(!retFeeInfo.used_addr_id) {
                    return callback('无地址信息', null);
                }
                var data = {};
                data.retFeeInfo = retFeeInfo;
                data.retGoods = retGoods;
                return callback(getErr, data);
            });
        });
        // 2. 拷贝地址
        totalTasks.push(function (data, callback) {
            orderUtil.copyAddress(data.retFeeInfo.used_addr_id, 10/*商品订单*/, function (cpErr, newAddrId) {
                data.newAddrId = newAddrId;
                if(newAddrId <=0) {
                    return callback('创建地址失败', data);
                }
                return callback(cpErr, data);
            });
        });
        // 3. 创建订单编号
        totalTasks.push(function (data, callback) {
            orderUtil.createOrderNo(options.device, 10/*商品订单*/, function (crtErr, newOrderNo) {
                data.newOrderNo = newOrderNo;
                return callback(crtErr, data);
            });
        });
        // 4. 创建总订单
        totalTasks.push(function (data, callback) {
            // 子商品个数
            var itemCnt = data.retGoods.length;
            for(var i=0; i<data.retGoods.length; i++) {
                var goods = data.retGoods[i];
                if(goods.assyList) {
                    itemCnt += goods.assyList.length;
                }
            }
            // 新建总订单
            var newEntity = new ItbTradeOrderModel({
                order_no: data.newOrderNo,
                pay_order_no: data.newOrderNo,// 支付用
                detail_cnt: itemCnt,
                device: options.device,
                state: 10,  // 待支付
                partner_id: (Number(options.device||'0')===301)?3:(data.retFeeInfo.platform_id||1),// 1:紫云, 3:酒单网
                pay_platform: options.payPlatform, // 支付方式
                addr_id: data.newAddrId,
                express_type: 10,   // 邮费默认一起支付
                total_fee: Number(data.retFeeInfo.total_fee||'0'),//
                user_id: options.userId,
                update_by: options.userId
            });
            // 到付邮费
            if(options.mailType === 20) {
                newEntity.express_type=20;
                newEntity.total_fee = newEntity.total_fee - Number(data.retFeeInfo.mail_fee||'0');
            }
            data.totalFee = newEntity.total_fee;
            // 创建订单
            newEntity.saveToDB(function(saveErr, newOrderId){
                if(saveErr || !newOrderId){
                    return callback(saveErr || '创建订单失败', data);
                }
                data.newOrderId = newOrderId;
                return callback(saveErr, data);
            });
        });
        // 5. 循环创建子订单
        totalTasks.push(function (data, callback) {
            var tasks = [];
            for (var i=0; i<data.retGoods.length; i++) {
                tasks.push((function (index, goodsInfo) {
                    return function (callback) {
                        var opt = {
                            goodsInfo:goodsInfo,
                            mailType : options.mailType,
                            index : index,
                            orderId : data.newOrderId
                        };
                        orderUtil.createGoodsDetailOrder_v6_4(opt, callback);
                    }
                })(i, data.retGoods[i]));
            }
            async.series(tasks, function (error, result) {
                data.detailOrderInfo = result;
                return callback(error, data);
            });
        });
        // 6. 按需处理优惠券
        totalTasks.push(function (data, callback) {
            if(data.retFeeInfo.used_c_id <=0) {
                return callback(null, data);
            }
            orderUtil.bindCouponToTradeOrder_v5_2(options.userId, data.newOrderId, data.retFeeInfo.used_c_id, function (bindErr, bindRet) {
                data.bindCouponRet = bindRet;
                return callback(bindErr, data);
            });
        });
        // 顺序执行
        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            var ret = {
                orderId: data.newOrderId,
                orderNo: data.newOrderNo,
                totalFee: data.totalFee
            };
            return callback(error, ret);
        });
    };

    /**
     *  根据购物车内选中商品创建订单并获取支付参数
     *
     *  @author 王俊
     *  @date 2018-04-19
     *
     *  @param {Object} options
     *  @param {Number} options.device      设备标识, 见接口定义
     *  @param {Number} options.userId      用户唯一标识
     *  @param {Number} options.couponId    优惠券标识
     *  @param {Number} options.mailType    邮费支付方式
     *  @param {Number} options.addrId      地址标识
     *  @param {Number} options.payPlatform 支付方式 10 微信, 20 支付宝, 30 苹果内购
     *  @param {Function} callback          回调
     *                      err:             失败
     *                      data:            支付参数
     *
     */
    orderUtil.createOrderAndPay_app_v6_4 = function (options, callback) {
        var totalTasks = [];
        // 1. 获取地址
        totalTasks.push(function (callback) {
            orderUtil.getUserAddressIdForSettlement_v5_7(options.userId, options.addrId, function(addrErr, addrId){
                if (addrErr || !addrId || addrId <=0) {
                    console.log('yjsc/v2/order.js [createOrderAndPay_v5_7] getUserAddressIdForSettlement_v5_7 Err: '+addrErr);
                    return callback(addrErr || '参数错误',null);
                }
                var data = {};
                data.addrId = addrId;
                return callback(addrErr, data);
            });
        });
        // 2. 根据购物车创建订单
        totalTasks.push(function (data, callback) {
            orderUtil.createOrderFromCart_v6_4(options, function(crtErr, crtOrderInfo) {
                if (crtErr) {
                    console.log('yjsc/v2/order.js createOrderFromCart_v5_5 Err: ' + crtErr);
                    return callback(crtErr, data);
                }
                data.crtOrderInfo = crtOrderInfo;
                return callback(crtErr, data);
            });
        });
        // 3. 删除购物车内商品
        totalTasks.push(function (data, callback) {
            // 将选中商品从购物车删除
            orderUtil.removeSelectedGoodsFromShopCart_v5_5(options.userId, function(delErr, delRet){
                return callback(delErr,data);
            });
        });
        //4. 统一更新订单为支付失败
        totalTasks.push(function (data, callback) {
            // orderUtil.updOrderState = function(tradeObjId, tradeType, tradeState, totalFee, userId, callback
            var tradeObjId = data.crtOrderInfo.orderId;
            var tradeType = 10; // 商品订单
            var totalFee = data.crtOrderInfo.totalFee;
            var userId = options.userId;
            var tradeState = 12; // 支付失败
            orderUtil.updOrderState(tradeObjId, tradeType, tradeState, totalFee, userId, function (error, result) {
                return callback(error, data);
            });
        });
        // 5. 获取支付参数
        totalTasks.push(function (data, callback) {
            var opt = {
                userId : options.userId,
                orderId : data.crtOrderInfo.orderId,
                orderType : 10, // 购物车创建,为商品订单
                device : options.device
            };
            orderUtil.getOderPaymentParams(opt, function (error, payParams) {
                data.payParams = payParams;
                return callback(error, data);
            });
        });
        async.waterfall(totalTasks, function (error, data) {
            if(error) return callback(error, null);
            return callback(error, data.payParams);
        });
    };


    //------------------------------------------------------------------
    /* 拷贝地址信息.
     * 参数:addressId:地址id
     * 参数：orderType	商品订单: 10   发票订单: 20
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          newAddressId: 新地址id
     * */
    orderUtil.copyAddress = function(addressId,orderType, callback){
        var type =orderType; //  '地址类型：0用户地址管理 10商品订单 20发票订单'
        return (new ItbAddressModel).copyAddress(addressId,type, callback);

    };
    //------------------------------------------------------------------
    /* 创建各种类型的订单编号
     * 参数: device	 0表示从p0 表示从pc来的请求
     *                 1 标识一键生成iOS端
     *                 2 标识一键生成android端
     *                 3  标识一键生成 app 嵌入网页
     *                 4 标识一键生成 web 端
     *                 5 标识一键生成微信端
     *
     *                 101 表示pc美化大师/102表示pc wps/103表示wps android/104表示wps ios
     *                 201 标识利楚商务
     *                 301 标识酒单网
     * 参数  userId: 用户id
     * 参数  docId: 文档id
     * 参数  orderType	商品订单: 10   发票订单: 20   模版订单: 30   虚拟商品订单: 40   秒杀订单: 50
     * 参数： callback：回调，参数如下：
     *          error:错误消息
     *          order_no:新文档id
     */
    // 4：pc,5：ios,6：android,7: h5,8: 小程序，9:  app嵌入h5
    orderUtil.DEVICE_ID_MAP ={"0":4,"1":5,"2":6,"3":9,"4":4,"5":7,"201":7,"301":7};
    orderUtil.DEVICE_P01_FLAG_MAP ={
        "10":CONFIG.ORDER_TYPE_ORDER,
        "20":CONFIG.ORDER_TYPE_INVOICE,
        "30":CONFIG.ORDER_TYPE_TEMPLATE,
        "40":CONFIG.ORDER_TYPE_VIP,
        "50":CONFIG.ORDER_TYPE_SECKILL
    };
    orderUtil.createOrderNo = function(device, orderType, callback){
        var cur = CommonUtil.genCurYearDayTimeStr();
        var p00 = orderUtil.DEVICE_ID_MAP[device] || 0;// 标志
        var p01 = orderUtil.DEVICE_P01_FLAG_MAP[orderType] ||0; // 订单
        var p0 = p00+""+p01;
        var p1 = cur.substr(8); // 分秒
        var p2 = CommonUtil.randomNumStr(3); // 3位随机数
        var p3 = cur.substr(0,8);// 年月日时
        p3 = CommonUtil.yearDayTimeStrtoAlphabet(p3); // 4位26进制字符串
        var ret = CommonUtil.mix(p0+p1+p2, p3);
        return callback(null, ret);
    };

    //------------------------------------------------------------------
    /* 绑定/解绑优惠券至订单
     * 参数: userId   用户唯一标识
     * 参数: tradeOrderId 商品订单 id
     * 参数: couponId     优惠券 id
     * 注意: 	若订单已存在优惠券, 则先解绑优惠券再重新绑定
     *          若不使用优惠券则 传递 couponId 为 -1
     * */
    orderUtil.bindCouponToTradeOrder_v5_2 = function(userId, tradeOrderId, couponId, callback){

        async.parallel({
            orderInfo: function(cb){
                (new ItbTradeOrderModel).getOrderFeeInfo(tradeOrderId, function(getErr, getRet){
                    if(getErr){
                        console.log('orderUtil.js [bindCouponToTradeOrder_v5_2] getOrderFeeInfo Err:'+getErr);
                        return cb(getErr, null);
                    }

                    if(getRet && getRet.length>0) {
                        var retData = getRet[0]||{};
                        return cb(null, retData);
                    } else {
                        return cb(null, null);
                    }
                });
            },

            couponInfo: function(cb){
                var cId = Number(couponId||'0');
                if(cId == -1) {
                    return cb(null, {c_id:-1});

                } else {
                    var entity = new ItbCouponModel({
                        c_id: couponId,
                        del_flg: 0
                    });
                    entity.findFromDB(function(error, items){
                        if (error){
                            console.log('orderUtil.js [bindCouponToTradeOrder_v5_2] select coupon Err: '+error);
                            return cb(error, null);
                        }

                        if (items != null && items.length > 0) {
                            return cb(null, items[0]);
                        } else {
                            return cb(null, null);
                        }
                    });
                }
            }

        }, function(error, result) {
            if (error) {
                return callback(error, null);
            }

            var orderInfo = result.orderInfo;
            var couponInfo = result.couponInfo;

            if(orderInfo && orderInfo.order_id>0) {
                if(Number(orderInfo.user_id||'0') != userId) {
                    return callback('用户/订单不匹配', null)
                }

                if(couponInfo && Number(couponInfo.c_id||'0')!=0) {
                    if(Number(orderInfo.coupon_id||'0')!=0) {
                        // 当前订单已经绑定有优惠券
                        if(couponInfo.c_id>0 && couponInfo.c_id==orderInfo.coupon_id) {
                            // 将要绑定的优惠券与当前优惠券相同, 则认为已绑定成功
                            return callback(null, null);
                        }

                        // 解绑旧优惠券
                        var unbindOrderFee = Number(orderInfo.sum_fee||'0');
                        (new ItbCouponModel).unbindOrder(orderInfo.coupon_id, orderInfo.order_id, unbindOrderFee,
                            function(unbindErr, unbindRet){
                                if(unbindErr){
                                    return callback('解绑优惠券失败', null);
                                }

                                // 绑定新优惠券
                                if(couponInfo.c_id>0) {
                                    doBindOrder(orderInfo, couponInfo, function(doErr, doRet){
                                        return callback(doErr, null);
                                    });
                                } else {
                                    return callback(null, null);
                                }
                            }
                        );
                    } else {
                        // 当前订单未绑定优惠券
                        // 直接绑定优惠券
                        // 当前订单没有绑定优惠券, 且传递的优惠券 id 为-1 , 标记解绑优惠券, 直接返回
                        if(couponId < 0) {
                            return callback(null, null);
                        }

                        doBindOrder(orderInfo, couponInfo, function(doErr, doRet){
                            return callback(doErr, null);
                        });
                    }

                } else {
                    return callback('未检索到优惠券', null);
                }

            } else {
                return callback('未检索到订单', null);
            }
        });

        // 绑定新优惠券
        function doBindOrder(orderInfo, couponInfo, doCallback) {
            if(Number(orderInfo.order_id||'0')<=0 || Number(couponInfo.c_id||'0')<=0) {
                return doCallback('参数错误', null);
            }

            var discount = 0;// 实际优惠金额
            switch (Number(couponInfo.type||'0')) {
                case 10: {// 现金券
                    discount = Number(couponInfo.discount||'0');
                } break;
                case 20: {// 满减券
                    if( (Number(orderInfo.sum_fee||'0')-Number(orderInfo.sum_mail_fee||'0'))<Number(couponInfo.min_order_fee||'0')) {
                        return doCallback('该优惠券不满足使用条件', null);
                    }
                    discount = Number(couponInfo.discount||'0');
                } break;
                case 30: {// 折扣券
                    discount = (Number(orderInfo.sum_fee||'0')-Number(orderInfo.sum_mail_fee||'0'))*(1-couponInfo.discount/100);
                } break;
            }

            if( discount > (Number(orderInfo.sum_fee||'0')-Number(orderInfo.sum_mail_fee||'0')) ) {// 除去邮费
                discount = Number(orderInfo.sum_fee||'0')-Number(orderInfo.sum_mail_fee||'0');
            }

            var bindOrderFee = Number(orderInfo.sum_fee||'0') - discount;
            if(bindOrderFee<0) {
                bindOrderFee = 0;
            }

            (new ItbCouponModel).bindOrder(couponInfo.c_id, discount, orderInfo.order_id, bindOrderFee,
                function(bindErr, bindRet){
                    if(bindErr){
                        return doCallback('绑定优惠券失败', null);
                    }
                    return doCallback(null, bindRet);
                }
            );
        }
    };

    //------------------------------------------------------------------
    /**
     * 移除购物车中选中商品
     * @param userId
     * @param callback
     */
    orderUtil.removeSelectedGoodsFromShopCart_v5_5 = function(userId, callback) {
        var ent = new ItbCartModel;
        // 删除选中商品
        ent.removeSelectedGoods(userId, function(err, ret){
            return callback(err, ret);
        });
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API (APP支付用)
     * @param userId
     * @param openId (微信H5支付用)
     * @param tradeObjId: order_id 或 inv_id
     * @param type: 商品订单:10, 发票订单:20, 虚拟商品:40
     * @param callback
     *  {
     *      "prepayId": 1234567,
     *      "nonceStr": "qwertyuiopsdfghjkl",
     *      "timeStamp": 999990909090,
     *      "sign": "QWKSJDFHGJHDFHHDHH"
     *   }
     */
    orderUtil.getUnifiedOrder = function(device, userId, openId, tradeObjId, type, callback) {

        var H5PayFlg = false;
        if(device == '5' || device == '201' || device == '301') {// 微信内嵌H5支付
            H5PayFlg = true;
        }

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳

        var trade_type = "APP";// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        var openid = openId || "";

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify';
        if(CONFIG.DEBUG) {
            notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify';
        }
        var appid = ITB_WX_INFO.APPID;// 应用ID(必填)
        var mch_id = ITB_WX_INFO.MCH_ID;// 商户号(必填)
        var key = ITB_WX_INFO.KEY;

        if(H5PayFlg) {// 内嵌H5支付
            trade_type = 'JSAPI';
            appid = ITB_WX_INFO_2.APPID;
            mch_id = ITB_WX_INFO_2.MCH_ID;
            key = ITB_WX_INFO_2.KEY;
            notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify2';
            if(CONFIG.DEBUG) {
                notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify2';
            }
        }

        // 附加数据: 暂定纪录userId,tradeObjId,type
        var attach = JSON.stringify({
            uid: userId||0, id: tradeObjId||0, type: type||0
        });
        var body = "示界港微信支付订单";// 商品或支付单简要描述 TODO

        var nonce_str = orderUtil.genNonceStr(32);// 随机字符串,不长于32位(必填)

        var ip = "127.0.0.1";// 终端IP(必填) TODO

        var paramForSign = {
            appid: appid,
            attach: attach,
            body: body,
            mch_id: mch_id,
            nonce_str: nonce_str,
            notify_url: notify_url,
            openid: openid,
            out_trade_no: '',// 商户订单号(必填)
            spbill_create_ip: ip,
            total_fee: 0,// 总金额(必填)
            trade_type: trade_type
        };

        // 获取订单信息
        if(type == 10 || type == 20 || type == 40 || type == 50) {
            var orderEnt = null;

            if(type == 10 || type == 40 || type == 50) {// 商品订单
                orderEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId,
                    del_flg: 0
                });
            } else if(type == 20){// 发票订单
                orderEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId,
                    del_flg: 0
                });
            }
            orderEnt.findFromDB(function(error, data){
                if(data && data.length>0){

                    var curState = Number(data[0].state || '0');
                    if(curState == 11) {
                        return callback('该订单已支付成功，无需重复支付！', null);
                    } else if(curState == 50) {
                        return callback('该订单因超时已取消，请重新下单！', null);
                    }

                    paramForSign.out_trade_no = '';
                    if(type == 10 || type == 40 || type == 50) {
                        paramForSign.out_trade_no = data[0].order_no;
                        paramForSign.total_fee = data[0].total_fee || 0;// 商品订单总金额
                    } else if(type == 20) {
                        paramForSign.out_trade_no = data[0].inv_no;
                        paramForSign.total_fee = data[0].mail_fee || 0;// 发票只算邮费
                    }

                    // 先统一更新为支付失败
                    orderUtil.updOrderState(tradeObjId, type, 12, paramForSign.total_fee, userId,
                        function(updErr, updRet){
                            if (updErr) {
                                console.log("orderUtil.js [getUnifiedOrder] Upd State(12) Err: " + updErr);
                                return callback(updErr, null);
                            }

                            // 开始支付
                            if(paramForSign.total_fee == 0) {// 免费不用支付
                                // 添加支付历史纪录
                                var insEnt = new ItbPaymentHisModel({
                                    type: type||0,
                                    trade_obj_id: tradeObjId||0,
                                    trade_obj_no: paramForSign.out_trade_no||0,
                                    state: 11,
                                    pay_platform: 0,// 无
                                    desc: 'SUCCESS',
                                    update_by: userId||0
                                });
                                insEnt.saveToDB(function(insErr, newHisId) {
                                    if(insErr) {
                                        console.log("orderUtil.js [getUnifiedOrder] Ins PayHis Err: " + insErr);
                                    }

                                    orderUtil.updOrderState(tradeObjId, type, 11, 0, userId, function(updErr2, updRet2){
                                        if(updErr2) {
                                            return callback(updErr2, null);
                                        }

                                        console.log("orderUtil.js [getUnifiedOrder] Upd fee=0 Order ");

                                        // added 2017-06-14
                                        if(type==10) {
                                            // 尝试拆分支付成功的商品订单
                                            orderUtil.splitTradeOrder_v5_5(tradeObjId, userId, function(procErr, procRet){
                                                if(procErr) {
                                                    console.log("orderUtil.js [getUnifiedOrder] splitTradeOrder_v5_5 Err: "+procErr);
                                                }

                                                return  callback(updErr2, updRet2);
                                            });

                                        } else if(type==40) {
                                            // 虚拟商品特殊处理: 支付成功时直接[完成]
                                            orderUtil.updOrderState(tradeObjId, type, 40, 0, userId, function(updErr3, updRet3){

                                                    // 更新vip会员信息
                                                    orderUtil.updVipExpiryInfo(userId, tradeObjId, function(updErr4, updRet4){
                                                        return callback(updErr4, updRet4);
                                                    });
                                                }
                                            );

                                        } else if (type == 50){
                                            // 获取秒杀商品
                                            return callback('无效订单', null);
                                        } else {
                                            return  callback(updErr2, updRet2);
                                        }
                                    });
                                });

                            } else {// 需要支付
                                // 调用微信下单接口
                                var formData  = "<xml>";
                                formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                                formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                                formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                                formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                                formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                                formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                                formData  += "<openid>"+paramForSign.openid+"</openid>";
                                formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                                formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                                formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                                formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                                formData  += "<sign>"+orderUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                                formData  += "</xml>";

                                orderUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                                    if(retErr) {
                                        return callback(retErr, null);
                                    }

                                    if(retInfo && retInfo.prepay_id) {
                                        // 统一下单接口返回正常的prepay_id, 再按签名规范重新生成签名后, 将数据传输给APP。
                                        // 参与签名的字段名为appId, partnerId, prepayId, nonceStr, timeStamp, package。
                                        // 注意: package的值格式为Sign=WXPay

                                        //var paramForSign2 = {
                                        //    appId: appid,
                                        //    partnerId: mch_id,
                                        //    prepayId: retInfo.prepay_id,
                                        //    nonceStr: payUtil.genNonceStr(32),
                                        //    timeStamp: Math.floor(Date.now()/1000)+"",
                                        //    package: "Sign=WXPay"
                                        //};

                                        var paramForSign2 = {};
                                        var ns = orderUtil.genNonceStr(32);
                                        var ts = Math.floor(Date.now()/1000)+"";

                                        if(H5PayFlg) {// 内嵌H5支付
                                            paramForSign2 = {// 参数名区分大小写 !!!???
                                                appId: appid,
                                                timeStamp: ts,
                                                nonceStr: ns,
                                                package: "prepay_id="+retInfo.prepay_id,
                                                signType: 'MD5'
                                            };

                                        } else {// APP,网页支付
                                            paramForSign2 = {// 巨坑: 参数名需要小写 !!!???
                                                appid: appid,
                                                partnerid: mch_id,
                                                prepayid: retInfo.prepay_id,
                                                noncestr: ns,
                                                timestamp: ts,
                                                package: "Sign=WXPay"
                                            };
                                        }

                                        var sign2 = orderUtil.calcWxPaySign(key, paramForSign2);

                                        return callback(null, {
                                            prepayId:retInfo.prepay_id,
                                            nonceStr:ns,
                                            timeStamp:ts,
                                            sign:sign2
                                        });

                                    } else {
                                        return callback('预支付交易会话标识获取失败', null);
                                    }
                                });
                            }
                        }
                    );

                }else{
                    return callback(error, null);
                }
            }, 0, 1);

        } else {
            return callback('无效订单分类', null);
        }
    };


    //--------------------------------------------------------------------------------------------
    /**
     * 生成随机字符串
     * @param len: 字符串长度(默认32位)
     * @param flg: 1:纯数字; 2:纯字母; 其他(默认):数字+字母
     * @returns {string}
     */
    orderUtil.genNonceStr = function(len,flg){
        var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        if(flg == 1) {
            chars = '0123456789';
        } else if(flg == 2) {
            chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        }
        var maxPos = chars.length;
        var ret = "";
        var size = Number(len||'32');
        for(var i = 0; i < size; i++) {
            ret += chars.charAt(Math.floor(Math.random() * maxPos));
        }
        return ret;
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 更新订单状态
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单
     * @param tradeState: 订单状态
     * @param userId:     更新者
     * @param callback     返回
     *          error   错误，null表示整你却
     *          data    预留null
     */
    orderUtil.updOrderStateOnly = function(tradeObjId, tradeType, tradeState,userId, callback){
        // 更新订单状态
        if((Number(tradeType||0)==10 || Number(tradeType||0)==20) && tradeObjId) {
            var updEnt = null;
            if(Number(tradeType||0)== 10) {
                // 商品订单
                updEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||''
                });
            } else if(Number(tradeType||0)== 20) {
                // 发票订单
                updEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||'0'
                });
            } else{
                return callback(null,null);
            }
            updEnt.updateToDB(function(updErr){
                if(updErr){
                    console.log("orderUtil.js [updOrderStateOnly] Upd State Err: "+updErr);
                    var desc = '[ItbTradeOrderModel/ItbInvoiceModel] update [state] error';
                    return callback(desc,null);
                }

                return callback(null, null);
            });

        } else {
            return callback(null, null);// TODO
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 更新订单状态
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单 30模版订单 40虚拟商品 50秒杀订单
     * @param tradeState: 订单状态
     * @param totalFee:   订单金额
     * @param userId:     更新者
     * @param callback
     */
    orderUtil.updOrderState = function(tradeObjId, tradeType, tradeState, totalFee, userId, callback){

        tradeType = Number(tradeType||'0')||0;

        // 更新订单状态
        if( (tradeType==10 || tradeType==20 || tradeType==30 || tradeType==40 || tradeType==50)
            && tradeObjId ) {

            var updEnt = null;
            var hisDesc = '';
            if(tradeType== 10 || tradeType== 40 || tradeType==50) {
                // 商品订单
                updEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||''
                });
                if(tradeState==40) {
                    // 订单完成:需同步设置完成时间
                    updEnt.arrUpdSysDtFieldNm=['finish_time'];
                }
                hisDesc = '[ItbTradeOrderModel] Upd to [state:'+tradeState+']';

            } else if(tradeType== 20) {
                // 发票订单
                updEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||'0'
                });
                hisDesc = '[ItbInvoiceModel] Upd to [state:'+tradeState+']';

            } else if(tradeType== 30) {
                // 模版订单
                updEnt = new ItbBuyTmplModel({
                    buy_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||'0'
                });
                hisDesc = '[ItbBuyTmplModel] Upd to [state:'+tradeState+']';
            }
            updEnt.updateToDB_SysDt(function(updErr){
                if(updErr){
                    console.log("orderUtil.js [updOrderState] Upd State Err: "+updErr);
                    hisDesc += ' NG';
                } else {
                    hisDesc += ' OK';
                }

                // 添加状态变更纪录
                var hisEnt = new ItbTradeStateHisModel({
                    type: tradeType||0,
                    trade_obj_id: tradeObjId||0,
                    state: tradeState,
                    total_fee: totalFee||0,
                    desc: hisDesc,
                    user_id: userId||0,
                    update_by: userId||'0'
                });
                hisEnt.saveToDB(function(insErr, newHisId){
                    if(insErr){
                        console.log("orderUtil.js [updOrderState] Ins StateHis Err: "+insErr);
                        return callback(insErr,null);
                    }

                    // 更新绑定的优惠券状态
                    orderUtil.updConponState(tradeObjId, tradeType, tradeState, userId, function(updErr, updRet){

                        if(tradeType==10 || tradeType==20) {
                            // 在订单支付完成时:取得订单的快递地址，到“用户地址管理”表中查找是否有相同纪录，如果没有则拷贝地址到“用户地址管理”表
                            if(tradeState!=CONFIG.TRADE_ORDER_STATE_PAY_SUCCESS){
                                return callback(null,null);
                            }

                            orderUtil.tryCopyOrderAddressToUser(tradeObjId, tradeType, function (error, newUserAddressId) {
                                // 不用处理错误消息
                                return callback(null, null);
                            });

                        } else {
                            return callback(null, null);
                        }

                    });

                });
            });

        } else {
            return callback(null, null);// TODO
        }
    };


    //--------------------------------------------------------------------------------------------
    /**
     * 根据订单状态更新优惠券状态
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单 30模版订单 40虚拟商品
     * @param tradeState: 订单状态
     * @param userId:     更新者
     * @param callback
     */
   orderUtil.updConponState = function(tradeObjId, tradeType, tradeState, userId, callback) {
        if(Number(tradeType||'0')==10 || Number(tradeType||'0')==40 || Number(tradeType||'0')==50) {// 可用优惠券的订单类型

            if(tradeState==11) {
                // 支付成功
                (new ItbCouponModel).updStateByPaidOrder(tradeObjId, function(err, ret){
                    return callback(err, ret);
                });
            } else if(tradeState==50) {
                // 订单取消,解绑优惠券
                (new ItbCouponModel).unbindCanceledOrderOnly(tradeObjId, function(err, ret){
                    return callback(err, ret);
                });
            } else {
                return callback(null, null);
            }

        } else {
            return callback(null, null);
        }
   };

    //--------------------------------------------------------------------------------------------
    /**
     * 取得订单的快递地址，到“用户地址管理”表中查找是否有相同纪录，如果没有则拷贝地址到“用户地址管理”表
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单
     * @param callback  回调，参数如下：
     *                      error：错误
     *                      newUserAddressId： 新的用户地址
     */
    orderUtil.tryCopyOrderAddressToUser = function(tradeObjId, tradeType, callback){
        var orderEnt = null;

        // 取得订单地址
        if(tradeType == 10) {// 商品订单
            orderEnt = new ItbTradeOrderModel({
                order_id: tradeObjId,
                del_flg: 0
            });
        } else if(tradeType == 20){// 发票订单
            orderEnt = new ItbInvoiceModel({
                inv_id: tradeObjId,
                del_flg: 0
            });
        }
        orderEnt.findAddressFromDB(function(error, address){
            if(address){
                // 到“用户地址管理”表中查找是否有相同纪录，如果没有则拷贝地址到“用户地址管理”表
                (new ItbAddressModel).insertUserAddressIfNotExist(address, function(error, newUserAddressId){
                    return callback(error,newUserAddressId);
                });
            }else{
                return callback(error ,null);
            }

        });
    };

    //------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API
     * 参数 key: 密钥
     * 参数 formData: XML格式参数
     */
    orderUtil.reqWxApi_payUniOrd = function(key, formData, cb) {
        var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        request({url:url,method:'POST',body: formData},function(err,response,retBody){
            if(!err && response.statusCode == 200){
                console.log(retBody);
                //var prepay_id = getXMLNodeValue('prepay_id', retBody.toString("utf-8"));
                //if(prepay_id) {
                //  var tmp = prepay_id.split('[');
                //  var tmp2 = tmp[2].split(']');
                //  var prepayId = tmp2[0];
                //}

                var parser = new xml2js.Parser({ trim:true, explicitArray:false, explicitRoot:false });
                parser.parseString((retBody||'').toString("utf-8"), function(parseErr, parseRet){
                    if(parseErr) {
                        console.log('orderUtil.js [reqWxApi] parser xml Err: '+parseErr);
                        return cb(parseErr, null);
                    }

                    // 验证返回值签名
                    var retSign = parseRet.sign||'';
                    if(parseRet.sign){
                        delete parseRet.sign;
                    }
                    var calSign = orderUtil.calcWxPaySign(key, parseRet);

                    console.log('retSign:[' + retSign + '] calSign:[' + calSign + ']');
                    if (!retSign || !calSign || retSign.toUpperCase() != calSign.toUpperCase()) {
                        return cb('[微信统一下单]返回数据非法', null);
                    }

                    // [return_code] 此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断
                    if((parseRet.return_code||'')=='SUCCESS') {

                        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回:
                        // [trade_type]: 交易类型(调用接口提交的交易类型，取值如下：JSAPI，NATIVE，APP)
                        // [prepay_id]: 预支付交易会话标识,(微信生成的预支付回话标识，用于后续接口调用中使用，该值有效期为2小时)
                        if((parseRet.result_code||'')=='SUCCESS') {
                            parseRet.sign = retSign;
                            return cb(null, parseRet);
                        } else {
                            return cb(parseRet.err_code||'[微信统一下单]交易失败', null);
                        }

                    } else {
                        return cb(parseRet.return_msg||'[微信统一下单]通信失败', null);
                    }
                });
            } else {
                return cb(err, null);
            }
        });
    };


    //--------------------------------------------------------------------------------------------
    /**
     * 计算[微信支付]签名
     * @param key: 密钥
     * @param param: 参数
     * @returns {string}
     */
    orderUtil.calcWxPaySign = function(key, param) {
        var paramObj = param||{};
        var paramStr = orderUtil.toWxParamStr(paramObj);

        key = key || ITB_WX_INFO.KEY;

        paramStr = paramStr + '&key='+key;
        console.log("CalcParam: "+paramStr);
        var sign = crypto.createHash('md5').update(paramStr,'utf8').digest('hex');
        sign = sign.toUpperCase();
        console.log("CalcSign: "+sign);
        return sign;
    };
    //--------------------------------------------------------------------------------------------
    /**
     * 拼接参数字符串(eg: key1=value1&key2=value2…)
     * ◆ 参数名ASCII码从小到大排序（字典序）
     * ◆ 如果参数的值为空不参与签名
     * ◆ 参数名区分大小写
     * @param args: 字典对象
     * @returns {string}
     */
    orderUtil.toWxParamStr = function(args) {
        var keys = Object.keys(args);
        keys = keys.sort();
        var newArgs = {};
        keys.forEach(function (key) {
            if(args[key]!=null && (args[key]+'')!='') {// 过滤空值项
                //newArgs[key.toLowerCase()] = args[key];
                newArgs[key] = args[key];// 签名时候的参数不需要转换为小写的
            }
        });
        var string = '';
        for (var k in newArgs) {
            string += '&' + k + '=' + newArgs[k];
        }
        string = string.substr(1);
        return string;
    };


    /**
     * 创建[vip会员]订单
     * @param device 设备标识
     * @param itemId 虚拟商品id
     * @param userId 用户id
     * @param couponId 优惠券id
     * @param payPlatform 支付平台
     * @param callback 10 微信支付, 20 支付宝支付, 30 苹果内购
     */
    orderUtil.createVipMemberOrder_v6_4 = function(device, userId, itemId, couponId,payPlatform,callback) {
        var tasks = [];
        // 1.获取商品价格
        tasks.push(function(callback){
            (new ItbQtyPriceModel).findMinQtyPriceByItemId(itemId, function(findErr, priceInfo) {
                if (findErr) {
                    return callback(findErr, null);
                }
                if (priceInfo || priceInfo.length > 0) {
                    var data = {
                        priceInfo :priceInfo
                    };
                    return callback(null, data);
                } else {
                    return callback('未获取到价格信息', null);
                }
            });
        });
        //2. 创建订单编号
        tasks.push(function(data,callback){
            if(!data.priceInfo){
                return callback("未获取到价格信息", null);
            }
            //创建订单号
            orderUtil.createOrderNo(device, 40, function(crtErr, orderNo){
                if(orderNo) {
                    // 新建订单
                    var newEntity = new ItbTradeOrderModel({
                        order_no: orderNo,
                        pay_order_no: orderNo,
                        detail_cnt: 1,
                        device: device, // 记录来源
                        state: 10,// 待支付
                        type: 0,// 普通订单,未拆分
                        hide: 1,// 订单列表不显示
                        partner_id: 100,// 100:示界港
                        pay_platform: payPlatform,// 10微信, 20支付宝, 30苹果内购
                        total_fee: Number(data.priceInfo.price || '0'),
                        user_id: userId,
                        update_by: userId
                    });
                    // 创建订单
                    newEntity.saveToDB(function (saveErr, newOrderId) {
                        if (saveErr) {
                            return callback(saveErr, null);
                        }
                        if (!newOrderId) {
                            return callback('订单创建失败', null);
                        }
                        data.newOrderId = newOrderId;
                        return callback(null,data);
                    });
                }else{
                    return callback('创建订单失败', null);
                }
            });
        });
        //3. 创建子订单
        tasks.push(function(data,callback){
            if(!data.newOrderId){
                return callback('创建订单失败', null);
            }
            // 创建子订单
            var newEntity2 = new ItbTradeOrderDetailModel({
                detail_no: '0',
                order_id: data.newOrderId,
                item_id: itemId,
                pp_id: data.priceInfo.pp_id ,
                unit: data.priceInfo.unit,
                qty: data.priceInfo.min,
                //user_doc_id: null,
                fee: Number(data.priceInfo.price||'0'),
                product_fee: Number(data.priceInfo.price||'0'),
                design_fee: 0,
                mail_fee: 0,
                update_by: userId
            });
            // 创建子订单
            newEntity2.saveToDB(function(saveErr2, newOrderDetailId) {
                if (saveErr2) {
                    return callback(saveErr2, null);
                }
                if (!newOrderDetailId) {
                    return callback('子订单创建失败', null);
                }
                data.newOrderDetailId = newOrderDetailId;
                return callback(null,data);
            });
        });

        // 4.获取优惠券信息,并检测优惠券是否合法
        tasks.push(function(data,callback){
            if(!data.priceInfo){
                return callback("未获取到价格信息", null);
            }
            // 检查优惠券, 年度会员
            if(Number(couponId||'0')>0 &&  Number(data.priceInfo.pp_id) === 141) {
                // 检查优惠券
                (new ItbCouponModel).getCouponInfoById(couponId, function (chkErr, couponInfo) {
                    if (chkErr) {
                        return callback(chkErr, null);
                    }
                    if(couponInfo && Number(couponInfo.top_limit_type)===9) {// 虚拟商品用
                        // 绑定优惠券
                        orderUtil.bindCouponToTradeOrder_v5_2(userId, data.newOrderId, couponId, function (bindErr, bindRet) {
                            //获取支付参数
                            var opt = {
                                userId: userId,
                                orderId: data.newOrderId,
                                orderType: 40,//10商品订单,20发票,30购买模版,40虚拟商品(如vip),50秒杀订单
                                device: device
                            };
                            orderUtil.getOderPaymentParams(opt, function (err, payParamRes) {
                                if (err) {
                                    return callback(err, null);
                                }
                                data.payParamRes = payParamRes;
                                return callback(null, data);
                            });
                        });
                    }else {
                        return callback('无效优惠券', null);
                    }
                });
            }else {
                //获取支付参数
                var opt = {
                    userId: userId,
                    orderId: data.newOrderId,
                    orderType: 40,//10商品订单,20发票,30购买模版,40虚拟商品(如vip),50秒杀订单
                    device: device
                };
                orderUtil.getOderPaymentParams(opt, function (err, payParamRes) {
                    if (err) {
                        return callback(err, null);
                    }
                    data.payParamRes = payParamRes;
                    return callback(null, data);
                });
            }
        });
        async.waterfall(tasks,function(err,data){
            if(err){
                return callback(err,null);
            }
            if(!data.payParamRes){
                return callback("未获取到支付参数",null);
            }
            return callback(null,data.payParamRes);
        });
    };


    //--------------------------------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API (网页扫码支付用)
     * @param device
     * @param userId
     * @param tradeObjId: order_id 或 inv_id
     * @param type: 商品订单:10, 发票订单:20, 虚拟商品:40
     * @param callback
     *  {
     *      "prepay_id": "wx20170301114917740287da3c0256350262",
     *      "code_url": "weixin://wxpay/bizpayurl?pr=8RODogK",// 二维码链接
     *   }
     */
    orderUtil.getUnifiedOrderWeb = function(device, userId, tradeObjId, type, callback) {

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳

        // 附加数据: 暂定纪录userId,tradeObjId,type
        var attach = JSON.stringify({
            uid: userId||0, id: tradeObjId||0, type: type||0
        });

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify';
        if(CONFIG.DEBUG) {
            notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify';
        }

        var key = ITB_WX_INFO.KEY;

        var paramForSign = {
            appid:              ITB_WX_INFO.APPID,// 应用ID(必填)
            attach:             attach,
            body:               "示界港微信支付订单",// 商品或支付单简要描述 TODO
            device_info:        'WEB',
            mch_id:             ITB_WX_INFO.MCH_ID,// 商户号(必填)
            nonce_str:          orderUtil.genNonceStr(32),// 随机字符串,不长于32位(必填)
            notify_url:         notify_url,
            out_trade_no:       '',// 商户订单号(必填)
            spbill_create_ip:   "127.0.0.1",// 终端IP(必填) TODO
            total_fee:          0,// 总金额(必填)
            trade_type:         'NATIVE'// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        };

        // 获取订单信息
        if(type == 10 || type == 20 || type == 40 || type == 50) {
            var orderEnt = null;

            if(type == 10 || type == 40 || type == 50) {// 商品订单
                orderEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId,
                    del_flg: 0
                });
            } else if(type == 20){// 发票订单
                orderEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId,
                    del_flg: 0
                });
            }
            orderEnt.findFromDB(function(error, data){
                if(data && data.length>0){

                    if(Number(data[0].state || 0) == 50) {
                        return callback('该订单因超时已取消，请重新下单！', null);
                    }

                    if(type == 10 || type == 40 || type == 50) {
                        paramForSign.out_trade_no = data[0].order_no;
                        paramForSign.total_fee = data[0].total_fee || 0;// 商品订单总金额
                    } else if(type == 20) {
                        paramForSign.out_trade_no = data[0].inv_no;
                        paramForSign.total_fee = data[0].mail_fee || 0;// 发票只算邮费
                    }

                    // 先统一更新为[支付失败]
                    orderUtil.updOrderState(tradeObjId, type, 12, paramForSign.total_fee, userId,
                        function(updErr, updRet){
                            if (updErr) {
                                console.log("orderUtil.js [getUnifiedOrderWeb] Upd State(12) Err: " + updErr);
                                return callback(updErr, null);
                            }

                            // 开始支付
                            if(paramForSign.total_fee == 0) {// 免费不用支付
                                // 添加支付历史纪录
                                var insEnt = new ItbPaymentHisModel({
                                    type: type||0,
                                    trade_obj_id: tradeObjId||0,
                                    trade_obj_no: paramForSign.out_trade_no||0,
                                    state: 11,
                                    pay_platform: 0,// 无
                                    desc: 'SUCCESS',
                                    update_by: userId||0
                                });
                                insEnt.saveToDB(function(insErr, newHisId) {
                                    if (insErr) {
                                        console.log("orderUtil.js [getUnifiedOrderWeb] Ins PayHis Err: " + insErr);
                                    }
                                    // 更新为[支付成功]
                                    orderUtil.updOrderState(tradeObjId, type, 11, 0, userId,
                                        function(updErr2, updRet2){
                                            return  callback(updErr2, updRet2);
                                        }
                                    );

                                    // TODO 根据订单类型分别处理
                                });

                            } else {// 需要支付
                                // 调用微信下单接口
                                var formData  = "<xml>";
                                formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                                formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                                formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                                formData  += "<device_info>"+paramForSign.device_info+"</device_info>";
                                formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                                formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                                formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                                //formData  += "<openid>"+paramForSign.openid+"</openid>";
                                formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                                formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                                formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                                formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                                formData  += "<sign>"+orderUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                                formData  += "</xml>";

                                orderUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                                    if(retErr) {
                                        return callback(retErr, null);
                                    }

                                    if(retInfo && retInfo.prepay_id && retInfo.code_url) {
                                        return callback(null, {
                                            prepay_id:retInfo.prepay_id||'',// 预支付交易会话标识
                                            code_url:retInfo.code_url||''// 二维码链接
                                        });

                                    } else {
                                        return callback('[微信支付二维码]获取失败', null);
                                    }
                                });
                            }
                        }
                    );

                }else{
                    return callback(error, null);
                }
            }, 0, 1);

        } else {
            return callback('无效订单分类', null);
        }
    };


    //------------------------------------------------------------------
    /**
     * 更新发票订单
     * 参数: invId	发票订单id
     * 参数: info	"发票信息
     *       {
     *              "invoiceType" :1,  // 1表示公司，2表示个人
     *              "title" : "发票抬头",
     *              "content":"印刷费",
     *              "taxpayerId" : “1111", // 纳税人识别号
     *              "bank" : "开户行",
     *              "bankAccount" : "对公账户号",
     *              "address" : "发票地址",
     *              "mobile" : "电话"
     *       }
     * 返回：{
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          invId: 发票订单id
     * */
    orderUtil.modifyInvoiceOrder  = function(invId,info,payPlatform,callback){
        var newEntity = new ItbInvoiceModel({
            inv_id: invId,
            pay_platform : payPlatform
        });
        if(info.invoiceType){
            newEntity.type = info.invoiceType;
        }
        if(info.title){
            newEntity.title = info.title;
        }
        // 可修改发票抬头未以下四种之一
        if(info.content &&
            (info.content == '服务费' ||
            info.content == '设计费' ||
            info.content == '明细' ||
            info.content == '印品制作费')
        ){
            newEntity.content = info.content;
        }
        if(info.taxpayerId){
            newEntity.taxpayer_id = info.taxpayerId;
        }
        if(info.bank){
            newEntity.bank = info.bank;
        }
        if(info.bankAccount){
            newEntity.bank_account = info.bankAccount;
        }
        if(info.address){
            newEntity.address = info.address;
        }
        if(info.mobile){
            newEntity.mobile = info.mobile;
        }
        // 更新
        newEntity.updateToDB(function(error){
            if(error){
                return callback(error, null);
            }
            // 返回
            return callback(null, invId);
        });
    };


    return orderUtil;
})();
module.exports = orderUtil;